module type Sig = sig
  type t
  val to_string: t -> string
end

module Make(S: Sig) = struct
  include S

  let print v = v |> to_string |> print_string

  let println v = v |> to_string |> print_endline

  let print_vec v =
    print_char '[';
    List.iter (fun x -> x |> to_string |> Printf.printf "%s, ") v;
    print_endline "]"
end

module Int : (Sig with type t = int) = struct
  type t = int
  let to_string = string_of_int
end

module IntPrint = Make(Int)

module StringWithPrint(T: Sig) = struct
  include String

  type t = T.t
  let to_string = T.to_string
end
